/* eslint-disable react-refresh/only-export-components */
import React, { createContext, useReducer } from 'react';
import type { ReactNode } from 'react';
import type { Message, FileUploadStatus, User, ConnectionStatus } from '../types';

interface ChatState {
  user: User | null;
  messages: Message[];
  connectionStatus: ConnectionStatus;
  uploadingFiles: Map<string, FileUploadStatus>;
}

type ChatAction = 
  | { type: 'SET_USER'; payload: User }
  | { type: 'ADD_MESSAGE'; payload: Message }
  | { type: 'SET_MESSAGES'; payload: Message[] }
  | { type: 'DELETE_MESSAGE'; payload: string } // message id
  | { type: 'UPDATE_CONNECTION_STATUS'; payload: ConnectionStatus }
  | { type: 'START_FILE_UPLOAD'; payload: { fileHash: string; fileName: string; fileSize: number } }
  | { type: 'UPDATE_FILE_PROGRESS'; payload: { fileHash: string; progress: number } }
  | { type: 'UPDATE_MESSAGE_PROGRESS'; payload: { fileHash: string; progress: number } }
  | { type: 'COMPLETE_FILE_UPLOAD'; payload: { fileHash: string; filePath: string } }
  | { type: 'ERROR_FILE_UPLOAD'; payload: { fileHash: string } }
  | { type: 'SET_FILE_MESSAGE_COMPLETE'; payload: { fileHash: string; filePath: string; fileName?: string } }
  | { type: 'SET_FILE_MESSAGE_ERROR'; payload: { fileHash: string; errorMessage: string } }
  | { type: 'CLEAR_MESSAGES' };

interface ChatContextType {
  state: ChatState;
  dispatch: React.Dispatch<ChatAction>;
}

export const ChatContext = createContext<ChatContextType | undefined>(undefined);

const initialState: ChatState = {
  user: null,
  messages: [],
  connectionStatus: 'disconnected',
  uploadingFiles: new Map(),
};

function chatReducer(state: ChatState, action: ChatAction): ChatState {
  switch (action.type) {
    case 'SET_USER':
      return {
        ...state,
        user: action.payload,
      };
    
    case 'ADD_MESSAGE':
      return {
        ...state,
        messages: [...state.messages, action.payload],
      };
    
    case 'SET_MESSAGES':
      return {
        ...state,
        messages: action.payload,
      };
    
    case 'DELETE_MESSAGE':
      return {
        ...state,
        messages: state.messages.filter(msg => msg.id !== action.payload),
      };
    
    case 'UPDATE_CONNECTION_STATUS':
      return {
        ...state,
        connectionStatus: action.payload,
      };
    
    case 'START_FILE_UPLOAD': {
      const newUploadingFiles = new Map(state.uploadingFiles);
      newUploadingFiles.set(action.payload.fileHash, {
        fileName: action.payload.fileName,
        fileSize: action.payload.fileSize,
        progress: 0,
        status: 'uploading',
        fileHash: action.payload.fileHash,
      });
      return {
        ...state,
        uploadingFiles: newUploadingFiles,
      };
    }
    
    case 'UPDATE_FILE_PROGRESS': {
      const newUploadingFiles = new Map(state.uploadingFiles);
      const existingFile = newUploadingFiles.get(action.payload.fileHash);
      if (existingFile) {
        newUploadingFiles.set(action.payload.fileHash, {
          ...existingFile,
          progress: action.payload.progress,
        });
      }
      return {
        ...state,
        uploadingFiles: newUploadingFiles,
      };
    }
    
    case 'UPDATE_MESSAGE_PROGRESS': {
      // 仅更新最后一条匹配该 fileHash 的消息
      const messagesCopy = [...state.messages];
      for (let i = messagesCopy.length - 1; i >= 0; i--) {
        const msg = messagesCopy[i];
        if (msg.type === 'file' && msg.fileHash === action.payload.fileHash) {
          messagesCopy[i] = { ...msg, uploadProgress: action.payload.progress } as Message;
          break;
        }
      }
      return { ...state, messages: messagesCopy };
    }
    
    case 'SET_FILE_MESSAGE_COMPLETE': {
      const { fileHash, filePath, fileName } = action.payload;
      const messagesCopy = [...state.messages];
      for (let i = messagesCopy.length - 1; i >= 0; i--) {
        const msg = messagesCopy[i];
        if (msg.type === 'file' && msg.fileHash === fileHash) {
          messagesCopy[i] = {
            ...msg,
            filePath,
            uploadProgress: 100,
            message: `文件上传完成: ${fileName || (msg as any).fileName}`
          } as Message;
          break;
        }
      }
      return { ...state, messages: messagesCopy };
    }

    case 'SET_FILE_MESSAGE_ERROR': {
      const { fileHash, errorMessage } = action.payload;
      const messagesCopy = [...state.messages];
      for (let i = messagesCopy.length - 1; i >= 0; i--) {
        const msg = messagesCopy[i];
        if (msg.type === 'file' && msg.fileHash === fileHash) {
          messagesCopy[i] = {
            ...msg,
            message: errorMessage,
            uploadProgress: 0
          } as Message;
          break;
        }
      }
      return { ...state, messages: messagesCopy };
    }
    
    case 'COMPLETE_FILE_UPLOAD': {
      const newUploadingFiles = new Map(state.uploadingFiles);
      const existingFile = newUploadingFiles.get(action.payload.fileHash);
      if (existingFile) {
        newUploadingFiles.set(action.payload.fileHash, {
          ...existingFile,
          progress: 100,
          status: 'completed',
        });
        // Remove completed upload after a short delay
        setTimeout(() => {
          newUploadingFiles.delete(action.payload.fileHash);
        }, 2000);
      }
      return {
        ...state,
        uploadingFiles: newUploadingFiles,
      };
    }
    
    case 'ERROR_FILE_UPLOAD': {
      const newUploadingFiles = new Map(state.uploadingFiles);
      const existingFile = newUploadingFiles.get(action.payload.fileHash);
      if (existingFile) {
        newUploadingFiles.set(action.payload.fileHash, {
          ...existingFile,
          status: 'error',
        });
      }
      return {
        ...state,
        uploadingFiles: newUploadingFiles,
      };
    }
    
    case 'CLEAR_MESSAGES':
      return {
        ...state,
        messages: [],
      };
    
    default:
      return state;
  }
}

export function ChatProvider({ children }: { children: ReactNode }) {
  const [state, dispatch] = useReducer(chatReducer, initialState);

  return (
    <ChatContext.Provider value={{ state, dispatch }}>
      {children}
    </ChatContext.Provider>
  );
}

// useChat hook is now in a separate file